
const electron = require('electron');
const ipcMain = require('electron').ipcMain;
const dialog = require('electron').dialog;
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const ip = require("ip");
const path = require('path');
const url = require('url');
const fs = require('fs');
const md5 = require('blueimp-md5');

var static = require('node-static');
var http = require('http');
var server = null;

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
let playWindow;
let cfg;

ipcMain.setMaxListeners(0);

function createWindow() {
    mainWindow = new BrowserWindow({
        width: 1500,
        height: 1000,
    });

    mainWindow.setMenu(null);

    var content = fs.readFileSync(path.join(__dirname, 'config.json'), 'utf-8');
    cfg = JSON.parse(content);

    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, cfg.main),
        protocol: 'file:',
        slashes: true
    }));

    mainWindow.on('closed', function () {
        mainWindow = null;
    });

    if (cfg.debug) {
        mainWindow.openDevTools();
    }

    mainWindow.setTitle(cfg.name + ' [' + cfg.project + ']');
}

app.on('ready', createWindow);

app.on('window-all-closed', function () {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

app.on('activate', function () {
    if (mainWindow === null) {
        createWindow();
    }
});

ipcMain.on('debugtool', function (evt) {
    mainWindow.openDevTools();
    evt.returnValue = true;
});

ipcMain.on('server', function (evt, arg) {
    if (arg === 'open') {
        if (!server) {
            var folder = path.join(__dirname, 'www/player')
            var file = new static.Server(folder);

            server = http.createServer(function (request, response) {
                request.addListener('end', function () {
                    file.serve(request, response);
                }).resume();
            }).listen(3710);
        }
        evt.returnValue = 'http://' + ip.address() + ':3710';
    } else if (arg === 'close' && server) {
        server.close();
        server = null;
        evt.returnValue = 'Close Finish!';
    } else {
        evt.returnValue = 'ERROR';
    }
    evt.returnValue = 'ERROR';
});

ipcMain.on('reload', function (evt) {
    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, cfg.main),
        protocol: 'file:',
        slashes: true
    }));
    evt.returnValue = 'Finish!';
});

ipcMain.on('play', function (evt, bAll, bDebug) {
    playWindow = new BrowserWindow({
        width: 1500,
        height: 1000,
    });

    playWindow.setMenu(null);

    playWindow.loadURL(url.format({
        pathname: path.join(__dirname, bAll ? cfg.playall : cfg.playbatch),
        protocol: 'file:',
        slashes: true
    }));

    playWindow.on('closed', function () {
        playWindow = null;
    });

    if (bDebug === true) {
        playWindow.openDevTools();
    }

    playWindow.setTitle(cfg.name + ' [' + cfg.project + ']');
});

ipcMain.on('refresh-version', function (evt) {
    var url = path.join(cfg.project, 'version.json');
    var oldv = JSON.parse(fs.readFileSync(url, 'utf8'));
    var newv = {};
    var file3d = ['ani', 'mat', 'mdl', 'scn', 'geo'];
    var pathes = ['ani', 'cfg', 'img', 'vid', 'mat', 'mdl', 'scn', 'geo', 'aud', 'js', ''];
    var suffix = ['png', 'jpg', 'json', 'ani', 'mat', 'js', 'mdl', 'scn', 'geo', 'wav', 'ogg', 'mp3', 'ogv', 'mp4'];

    for (var i = 0; i !== pathes.length; ++i) {
        var type = pathes[i];
        var folder = path.join(cfg.project, type);
        var files = fs.readdirSync(folder);

        for (var j = 0; j !== files.length; ++j) {
            var file = files[j];
            var fileurl = path.join(folder, file);
            var stat = fs.statSync(fileurl);
            var split = file.split('.');
            var suff = split.pop();
            var name = split.join('.');

            if (stat.isDirectory() || suffix.indexOf(suff) === -1) {
                continue;
            }

            var vers = newv[type];
            if (vers === undefined) {
                vers = newv[type] = {};
            }

            var resname = file3d.indexOf(suff) === -1 ? file : name;

            var old = oldv[type] && oldv[type][resname];
            var md5code = md5(fs.readFileSync(fileurl));

            if (old) {
                if (old.md5 === md5code) {
                    vers[resname] = old;
                } else {
                    old.version++;
                    old.md5 = md5code;
                    old.size = stat.size;
                    vers[resname] = old;
                }
            } else {
                vers[resname] = {
                    md5: md5code,
                    version: 1,
                    size: stat.size
                }
            }
        }
    }

    fs.writeFileSync(url, JSON.stringify(newv, '\t', 2));

    evt.returnValue = 'Finish!';
});

ipcMain.on('rename', (evt, arg) => {
    try {
        fs.renameSync(arg.oldPath, arg.newPath);
        evt.returnValue = true;
    } catch (e) {
        evt.returnValue = false;
    }
});

ipcMain.on('delete', (evt, path) => {
    try {
        fs.unlinkSync(path);
        evt.returnValue = true;
    } catch (e) {
        evt.returnValue = false;
    }
});

ipcMain.on('save_file', (evt, arg) => {
    try {
        if (arg.base64) {
            fs.writeFileSync(arg.filename, arg.data, 'base64');
        } else {
            fs.writeFileSync(arg.filename, arg.data);
        }
        evt.returnValue = true;
    } catch (e) {
        evt.returnValue = false;
    }
});

ipcMain.on('read_file', (evt, url) => {
    try {
        evt.returnValue = fs.readFileSync(url, 'utf8');
    } catch (e) {
        console.log("ERROR: Can not read file", url);
        evt.returnValue = '';
    }
});

ipcMain.on('read_binary', (evt, url) => {
    try {
        let buff = fs.readFileSync(url);
        let base64data = buff.toString('base64');
        evt.returnValue = base64data;
    } catch (e) {
        console.log("ERROR: Can not read file", url);
        evt.returnValue = '';
    }
});

ipcMain.on('exists', (evt, url) => {
    evt.returnValue = fs.existsSync(url).toString().toLowerCase();
});

ipcMain.on('list-files', (evt, type) => {
    fs.readdir(path.join(cfg.project, type), function (err, files) {
        if (!err) {
            evt.returnValue = JSON.stringify(files);
        } else {
            console.error(err);
            evt.returnValue = '[]';
        }
    });
});

function createProject(project) {
    var subdirs = ['mdl', 'img', 'mat', 'scn', 'ani', 'cfg', 'geo', 'aud', 'js', 'vid'];
    for (var i = 0; i !== subdirs.length; ++i) {
        var subdir = path.join(project, subdirs[i]);
        (function (subdir) {
            fs.exists(subdir, (exists) => {
                console.log(subdir + " : " + exists);
                if (!exists) {
                    fs.mkdir(subdir, 0777, (err) => { });
                }
            });
        }(subdir));
    }

    var defaultConfig = {
        version: cfg.version,
        alpha: false,
        antialias: false,
        preserveDrawingBuffer: false,
        shadowMapType: 1,
        design_size: { x: 1920, y: 1080 },
        textures: {},
        effects: {},
        widgets: {},
        audios: {},
        dragonbones: [],
        batches: {}
    };

    let url = path.join(project, 'config.json');
    if (!fs.existsSync(url)) {
        fs.writeFileSync(url, JSON.stringify(defaultConfig, '\t', 2));
    } else {
        var config = fs.readFileSync(url, 'utf8');
        config = JSON.parse(config);
        config = Object.assign({}, defaultConfig, config);
        config.version = cfg.version;
        fs.writeFileSync(url, JSON.stringify(config, '\t', 2));
    }

    url = path.join(project, 'version.json');
    if (!fs.existsSync(url)) {
        fs.writeFileSync(url, '{}');
    }
}

function selectProject() {
    let folders = dialog.showOpenDialog({
        properties: ['createDirectory', 'openDirectory']
    });
    if (folders && folders.length !== 0) {
        var project = folders[0] + '/';
        cfg.project = project;
        mainWindow.setTitle(cfg.name + '  [' + project + ']');
        createProject(project);
        fs.writeFileSync(path.join(__dirname, 'config.json'), JSON.stringify(cfg, '\t', 2));
        return project;
    } else {
        return '';
    }
}

ipcMain.on('project', (evt) => {
    if (cfg && cfg.project) {
        if (!fs.existsSync(cfg.project)) {
            cfg.project = selectProject();
        } else {
            createProject(cfg.project);
        }
    }

    if (cfg.project === '') {
        app.quit();
    }

    evt.returnValue = cfg.project;
});

ipcMain.on('project-open', (evt) => {
    evt.returnValue = selectProject();
});

ipcMain.on('play-folder', (evt) => {
    evt.returnValue = path.join(__dirname, 'www/player');
});

ipcMain.on('theme', (evt, t) => {
    if (t) {
        cfg.theme = t;
        fs.writeFileSync(path.join(__dirname, 'config.json'), JSON.stringify(cfg, '\t', 2));
        evt.returnValue = t;
    } else {
        var theme = cfg ? cfg.theme : 'light';
        evt.returnValue = theme || 'light';
    }
});

ipcMain.on('language', (evt, lang) => {
    if (lang) {
        cfg.lang = lang;
        fs.writeFileSync(path.join(__dirname, 'config.json'), JSON.stringify(cfg, '\t', 2));
        evt.returnValue = lang;
    } else {
        var language = cfg ? cfg.lang : 'EN';
        evt.returnValue = language || 'EN';
    }
});
